{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "_cell_guid": "b1076dfc-b9ad-4769-8c92-a6c4dae69d19",
    "_uuid": "8f2839f25d086af736a60e9eeb907d3b93b6e0e5",
    "execution": {
     "iopub.execute_input": "2022-04-29T10:26:05.10223Z",
     "iopub.status.busy": "2022-04-29T10:26:05.101883Z",
     "iopub.status.idle": "2022-04-29T10:27:14.788548Z",
     "shell.execute_reply": "2022-04-29T10:27:14.787753Z",
     "shell.execute_reply.started": "2022-04-29T10:26:05.10216Z"
    }
   },
   "outputs": [],
   "source": [
    "\n",
    "# 下载数据集，这边我放在阿里云oss上面了，由于下载流量需要付费，所以我就不开放了\n",
    "!wget -O GTZAN.zip 'https://file.fishei.cn/GTZAN.zip' --no-check-certificate\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-29T10:27:14.790824Z",
     "iopub.status.busy": "2022-04-29T10:27:14.790481Z",
     "iopub.status.idle": "2022-04-29T10:27:15.454657Z",
     "shell.execute_reply": "2022-04-29T10:27:15.453817Z",
     "shell.execute_reply.started": "2022-04-29T10:27:14.790783Z"
    }
   },
   "outputs": [],
   "source": [
    "# 解压\n",
    "!unzip GTZAN\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:10:48.506625Z",
     "iopub.status.busy": "2022-04-25T01:10:48.50635Z",
     "iopub.status.idle": "2022-04-25T01:11:23.37502Z",
     "shell.execute_reply": "2022-04-25T01:11:23.374268Z",
     "shell.execute_reply.started": "2022-04-25T01:10:48.506586Z"
    }
   },
   "outputs": [],
   "source": [
    "# 下载测试集数据\n",
    "!wget -O GTZAN_TEST.zip 'https://file.fishei.cn/GTZAN_TEST.zip' --no-check-certificate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 解压测试集数据\n",
    "!unzip GTZAN_TEST.zip"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:11:26.860176Z",
     "iopub.status.busy": "2022-04-25T01:11:26.859879Z",
     "iopub.status.idle": "2022-04-25T01:11:37.538502Z",
     "shell.execute_reply": "2022-04-25T01:11:37.537671Z",
     "shell.execute_reply.started": "2022-04-25T01:11:26.860134Z"
    }
   },
   "outputs": [],
   "source": [
    "# 安装torchsummary\n",
    "!pip install torchsummary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:12:54.398331Z",
     "iopub.status.busy": "2022-04-25T01:12:54.398021Z",
     "iopub.status.idle": "2022-04-25T01:12:54.406079Z",
     "shell.execute_reply": "2022-04-25T01:12:54.40533Z",
     "shell.execute_reply.started": "2022-04-25T01:12:54.398296Z"
    }
   },
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "from torch.utils.tensorboard import SummaryWriter\n",
    "from torch.utils.data import Dataset\n",
    "import torchaudio\n",
    "from torch.utils.data import DataLoader\n",
    "import pandas as pd\n",
    "import os\n",
    "from itertools import product\n",
    "from collections import namedtuple\n",
    "from collections import OrderedDict\n",
    "from IPython.display import display,clear_output\n",
    "import time\n",
    "import json\n",
    "from torchsummary import summary\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "torch.set_printoptions(linewidth=120)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:12:58.357786Z",
     "iopub.status.busy": "2022-04-25T01:12:58.357318Z",
     "iopub.status.idle": "2022-04-25T01:12:58.467894Z",
     "shell.execute_reply": "2022-04-25T01:12:58.467203Z",
     "shell.execute_reply.started": "2022-04-25T01:12:58.357642Z"
    }
   },
   "outputs": [],
   "source": [
    "# 将标签文件的标签风格字母列表增加一列为数字格式\n",
    "# 测试集\n",
    "ANNOTATIONS_FILE = \"./GTZAN_TEST/features_30_sec_test.csv\"\n",
    "dataframe = pd.read_csv(ANNOTATIONS_FILE)\n",
    "\n",
    "labels = set()\n",
    "for row in range(len(dataframe)):\n",
    "    labels.add(dataframe.iloc[row, -1])\n",
    "labels_list = []\n",
    "for label in labels:\n",
    "    labels_list.append(label)\n",
    "sorted_labels = sorted(labels_list)\n",
    "sorted_labels\n",
    "mapping = {}\n",
    "for index, label in enumerate(sorted_labels):\n",
    "    mapping[label] = index\n",
    "dataframe[\"num_label\"] = dataframe[\"label\"]\n",
    "new_dataframe = dataframe.replace({\"num_label\": mapping})\n",
    "new_dataframe"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:13:02.525986Z",
     "iopub.status.busy": "2022-04-25T01:13:02.525664Z",
     "iopub.status.idle": "2022-04-25T01:13:02.5594Z",
     "shell.execute_reply": "2022-04-25T01:13:02.558793Z",
     "shell.execute_reply.started": "2022-04-25T01:13:02.52595Z"
    }
   },
   "outputs": [],
   "source": [
    "new_dataframe.to_csv(\"features_30_sec_test_final.csv\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:13:05.133222Z",
     "iopub.status.busy": "2022-04-25T01:13:05.132637Z",
     "iopub.status.idle": "2022-04-25T01:13:05.206444Z",
     "shell.execute_reply": "2022-04-25T01:13:05.205653Z",
     "shell.execute_reply.started": "2022-04-25T01:13:05.133182Z"
    }
   },
   "outputs": [],
   "source": [
    "# 训练集 数据集\n",
    "import pandas as pd\n",
    "ANNOTATIONS_FILE = \"./GTZAN/features_30_sec.csv\"\n",
    "dataframe = pd.read_csv(ANNOTATIONS_FILE)\n",
    "labels = set()\n",
    "for row in range(len(dataframe)):\n",
    "    labels.add(dataframe.iloc[row, -1])\n",
    "labels_list = []\n",
    "for label in labels:\n",
    "    labels_list.append(label)\n",
    "sorted_labels = sorted(labels_list)\n",
    "mapping = {}\n",
    "for index, label in enumerate(sorted_labels):\n",
    "    mapping[label] = index\n",
    "dataframe[\"num_label\"] = dataframe[\"label\"]\n",
    "new_dataframe = dataframe.replace({\"num_label\": mapping})\n",
    "new_dataframe"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:13:08.256198Z",
     "iopub.status.busy": "2022-04-25T01:13:08.255933Z",
     "iopub.status.idle": "2022-04-25T01:13:08.322075Z",
     "shell.execute_reply": "2022-04-25T01:13:08.321347Z",
     "shell.execute_reply.started": "2022-04-25T01:13:08.256171Z"
    }
   },
   "outputs": [],
   "source": [
    "new_dataframe.to_csv(\"features_30_sec_final.csv\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:13:09.924601Z",
     "iopub.status.busy": "2022-04-25T01:13:09.92417Z",
     "iopub.status.idle": "2022-04-25T01:13:09.929642Z",
     "shell.execute_reply": "2022-04-25T01:13:09.928918Z",
     "shell.execute_reply.started": "2022-04-25T01:13:09.924559Z"
    }
   },
   "outputs": [],
   "source": [
    "# RunBuild类，对超参数进行管理，对预先设定的超参数在训练过程中可自动组合训练\n",
    "class RunBuilder():\n",
    "    @staticmethod\n",
    "    def get_runs(params):\n",
    "        Run = namedtuple('Run', params.keys())\n",
    "        \n",
    "        runs = []\n",
    "        \n",
    "        for element in product(*params.values()):\n",
    "            runs.append(Run(*element))\n",
    "        \n",
    "        return runs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:13:10.547747Z",
     "iopub.status.busy": "2022-04-25T01:13:10.547319Z",
     "iopub.status.idle": "2022-04-25T01:13:10.571659Z",
     "shell.execute_reply": "2022-04-25T01:13:10.57098Z",
     "shell.execute_reply.started": "2022-04-25T01:13:10.547713Z"
    }
   },
   "outputs": [],
   "source": [
    "# 运行时的数据管理类\n",
    "class RunManager():\n",
    "    def __init__(self):\n",
    "        #训练集\n",
    "        # epoch 的数量\n",
    "        self.epoch_count = 0\n",
    "        # 每一epoch的损失值\n",
    "        self.epoch_loss = 0\n",
    "        # 每一epoch的正确预测数量\n",
    "        self.epoch_correct_num = 0\n",
    "        # 每一epoch的开始训练时间\n",
    "        self.epoch_start_time = None\n",
    "        \n",
    "        # 测试集\n",
    "        self.test_epoch_count = 0\n",
    "        self.test_epoch_loss = 0\n",
    "        self.test_epoch_correct_num = 0\n",
    "        \n",
    "        \n",
    "        # 每一run的超参数、循环次数等\n",
    "        self.run_params = None\n",
    "        self.run_count = 0\n",
    "        self.run_data = []\n",
    "        self.run_start_time = None\n",
    "        \n",
    "        \n",
    "        self.network = None\n",
    "        self.loader = None\n",
    "        # tensorboard\n",
    "        self.tb = None\n",
    "    \n",
    "    def begin_run(self, run, network, loader, test_loader):\n",
    "        # 初始化启动时间\n",
    "        self.run_start_time = time.time()\n",
    "        # 初始化超参数\n",
    "        self.run_params = run\n",
    "        # run 次数+1\n",
    "        self.run_count += 1\n",
    "        \n",
    "        self.network = network\n",
    "        self.loader = loader\n",
    "        self.test_loader = test_loader\n",
    "        # 加载tensorboard\n",
    "        self.tb = SummaryWriter(comment=f'-{run}')\n",
    "        \n",
    "        # signal：采样信号 sr：采样频率\n",
    "        signal, sr, address = next(iter(self.loader))\n",
    "        \n",
    "        \n",
    "        # 这边缺少信号转化为mel-spectrum，暂时未添加图片可视化\n",
    "        \n",
    "        # 神经网络结构图像可视化\n",
    "        self.tb.add_graph(\n",
    "            self.network,\n",
    "            signal.to(run.device)\n",
    "        )\n",
    "        \n",
    "    def end_run(self):\n",
    "        # 关闭 tensorboard 写入数据\n",
    "        self.tb.close()\n",
    "        # 每个epoch再重新计数\n",
    "        self.epoch_count = 0\n",
    "        self.test_epoch_count = 0\n",
    "        \n",
    "    def begin_epoch(self):\n",
    "        self.epoch_start_time = time.time()\n",
    "        self.epoch_count += 1\n",
    "        self.epoch_loss = 0\n",
    "        self.epoch_correct_num = 0\n",
    "        \n",
    "        self.test_epoch_count += 1\n",
    "        self.test_epoch_loss = 0\n",
    "        self.test_epoch_correct_num = 0\n",
    "        \n",
    "    def end_epoch(self):\n",
    "        epoch_duration = time.time() - self.epoch_start_time\n",
    "        run_duration = time.time() - self.run_start_time\n",
    "\n",
    "        # 训练集损失值\n",
    "        loss = self.epoch_loss / len(self.loader.dataset)\n",
    "        # 测试集准确率\n",
    "        accuracy = self.epoch_correct_num / len(self.loader.dataset)\n",
    "        print(f'正确率：{self.epoch_correct_num} / {len(self.loader.dataset)}')\n",
    "        \n",
    "        # 测试集 test\n",
    "        # print(f\"{self.test_epoch_correct_num}+{len(self.test_loader.dataset)}\")\n",
    "        test_loss = self.test_epoch_loss / len(self.test_loader.dataset)\n",
    "        test_accuracy = self.test_epoch_correct_num / len(self.test_loader.dataset)\n",
    "        \n",
    "        # 加入损失函数图像\n",
    "        self.tb.add_scalars('Loss', {\"train_loss\": loss, \n",
    "                                    \"test_loss\": test_loss}, self.epoch_count)\n",
    "        # 加入准确度函数图像\n",
    "        self.tb.add_scalars('Accuracy', {\"train_accuracy\": accuracy, \n",
    "                                        \"test_accuracy\": test_accuracy}, self.epoch_count)\n",
    "        \n",
    "        # self.tb.add_scalar('Test_Loss', test_loss, self.epoch_count)\n",
    "        \n",
    "        #self.tb.add_scalar('Test_Accuracy', test_accuracy, self.epoch_count)\n",
    "        \n",
    "        for name, param in self.network.named_parameters():\n",
    "            # 神经网络每一层的值\n",
    "            self.tb.add_histogram(name, param, self.epoch_count)\n",
    "            # 每一层值所对应的梯度\n",
    "            self.tb.add_histogram(f'{name}.grad', param.grad, self.epoch_count)\n",
    "\n",
    "        results = OrderedDict()\n",
    "\n",
    "        results['run'] = self.run_count\n",
    "        results['epoch'] = self.epoch_count\n",
    "        results['loss'] = loss\n",
    "        results['accuracy'] = accuracy\n",
    "        results['epoch duration'] = epoch_duration\n",
    "        results['run duration'] = run_duration\n",
    "\n",
    "        for k, v in self.run_params._asdict().items():\n",
    "            results[k] = v\n",
    "\n",
    "        self.run_data.append(results)\n",
    "\n",
    "        df = pd.DataFrame.from_dict(self.run_data, orient='columns')\n",
    "\n",
    "        clear_output(wait = True)\n",
    "        display(df)\n",
    "        \n",
    "    # def test_view(self):\n",
    "        \n",
    "    # 作业核心数\n",
    "    def get_num_workers(self,num_workers):\n",
    "        self.epoch_num_workers = num_workers\n",
    "\n",
    "    # 记录每一epoch的损失 训练集    \n",
    "    def track_loss(self,loss,batch):\n",
    "        self.epoch_loss += loss.item()*batch[0].shape[0]\n",
    "    \n",
    "    # 测试集\n",
    "    def test_loss(self,test_loss, test_batch):\n",
    "         self.test_epoch_loss += test_loss.item()*test_batch[0].shape[0]\n",
    "    \n",
    "    # 记录每一epoch上测试正确的数量 测试集\n",
    "    def test_num_correct(self, test_preds, test_labels):\n",
    "        \n",
    "        self.test_epoch_correct_num += self.get_correct_num(test_preds, test_labels)\n",
    "        \n",
    "    # 训练集\n",
    "    def track_num_correct(self, preds, labels):\n",
    "        self.epoch_correct_num += self.get_correct_num(preds, labels)\n",
    "    \n",
    "    def get_correct_num(self, preds, labels):\n",
    "        return preds.argmax(dim=1).eq(labels).sum().item()\n",
    "    \n",
    "    # 训练数据保存CSV文件中\n",
    "    def save(self, fileName):\n",
    "        pd.DataFrame.from_dict(\n",
    "            self.run_data, orient='columns'\n",
    "        ).to_csv(f'{fileName}.csv')\n",
    "        \n",
    "        with open(f'{fileName}.json', 'w', encoding='utf-8') as f:\n",
    "            json.dump(self.run_data, f, ensure_ascii=False, indent=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:13:11.084Z",
     "iopub.status.busy": "2022-04-25T01:13:11.083361Z",
     "iopub.status.idle": "2022-04-25T01:13:15.391828Z",
     "shell.execute_reply": "2022-04-25T01:13:15.390077Z",
     "shell.execute_reply.started": "2022-04-25T01:13:11.083958Z"
    }
   },
   "outputs": [],
   "source": [
    "# 数据预处理类\n",
    "# 这边的注释\n",
    "class GTZANDataset(Dataset):\n",
    "    def __init__(self,\n",
    "                 annotations_file,\n",
    "                 audio_dir,\n",
    "                 transformation,\n",
    "                 target_sample_rate,\n",
    "                 num_samples,\n",
    "                 device):\n",
    "        # 读取标签文件\n",
    "        self.annotations = pd.read_csv(annotations_file)\n",
    "        # 读取音频地址\n",
    "        self.audio_dir = audio_dir\n",
    "        # 设置设备\n",
    "        self.device = device\n",
    "        # 加梅尔频谱数据加载到设备中\n",
    "        self.transformation = transformation.to(self.device)\n",
    "        # 设定采样频率\n",
    "        self.target_sample_rate = target_sample_rate\n",
    "        # 设定采样数量\n",
    "        self.num_samples = num_samples\n",
    "        \n",
    "        \n",
    "    # 返回有多少个音频文件\n",
    "    def __len__(self):\n",
    "        return len(self.annotations)\n",
    "\n",
    "    \n",
    "    # 数组的方式可获得音频的数据、标签、路径\n",
    "    def __getitem__(self, index):\n",
    "        # 获得歌曲路径\n",
    "        audio_sample_path = self._get_audio_sample_path(index)\n",
    "        # 获得标签\n",
    "        label = self._get_audio_sample_label(index)\n",
    "        # signal 采样信号 sr 采样频率\n",
    "        signal, sr = torchaudio.load(audio_sample_path)\n",
    "        signal = signal.to(self.device)\n",
    "        # 控制采样频率\n",
    "        signal = self._resample_if_necessary(signal, sr)\n",
    "        # 双通道->单通道\n",
    "        signal = self._mix_down_if_necessary(signal)\n",
    "        # 控制采样数量\n",
    "        signal = self._cut_if_necessary(signal)\n",
    "        signal = self._right_pad_if_necessary(signal)\n",
    "        # 转化下mel频谱\n",
    "        signal = self.transformation(signal)\n",
    "        return signal, label, audio_sample_path\n",
    "\n",
    "    \n",
    "    # 是否需要对信号裁剪： 如果采数量 > 设定的数量 -> 裁剪\n",
    "    def _cut_if_necessary(self, signal):\n",
    "        # print('_cut_if_necessary')\n",
    "        if signal.shape[1] > self.num_samples:\n",
    "            signal = signal[:, :self.num_samples]\n",
    "        return signal\n",
    "    \n",
    "    \n",
    "    # 是否需要对信号补充： 向右填0补充，如果采数量 < 设定的数量 -> 补充\n",
    "    def _right_pad_if_necessary(self, signal):\n",
    "        length_signal = signal.shape[1]\n",
    "        # print('_right_pad_if_necessary')\n",
    "        if length_signal < self.num_samples:\n",
    "            \n",
    "            num_missing_samples = self.num_samples - length_signal\n",
    "            last_dim_padding = (0, num_missing_samples)\n",
    "            # last_dim_padding.to(self.device)\n",
    "            \n",
    "            signal = torch.nn.functional.pad(signal, last_dim_padding)\n",
    "\n",
    "        return signal\n",
    "\n",
    "    \n",
    "    # 重新设定采样频率\n",
    "    def _resample_if_necessary(self, signal, sr):\n",
    "        # print('_resample_if_necessary')\n",
    "        # 如果实际的采样频率没有和设定的一致，那么才重新设定\n",
    "        if sr != self.target_sample_rate:\n",
    "            resampler = torchaudio.transforms.Resample(sr, self.target_sample_rate).to(self.device)\n",
    "            signal = resampler(signal)\n",
    "            # signal = torchaudio.functional.resample(signal, sr, self.target_sample_rate)\n",
    "            \n",
    "        return signal\n",
    "\n",
    "\n",
    "    # 将音频的双通道改为单通道\n",
    "    def _mix_down_if_necessary(self, signal):\n",
    "        # print('_mix_down_if_necessary')\n",
    "        # 通道数大于1 就 取均值变成单通道\n",
    "        if signal.shape[0] > 1:\n",
    "            signal = torch.mean(signal, dim=0, keepdim=True)\n",
    "        return signal\n",
    "\n",
    "    # 对音频路径进行拼接提取\n",
    "    def _get_audio_sample_path(self, index):\n",
    "        # print('_get_audio_sample_path')\n",
    "        fold = f\"{self.annotations.iloc[index, -2]}\"\n",
    "        path = os.path.join(self.audio_dir, fold, self.annotations.iloc[\n",
    "            index, 1])\n",
    "        return path\n",
    "    \n",
    "    \n",
    "    # 从csv文件中提取出标签\n",
    "    def _get_audio_sample_label(self, index):\n",
    "        # print('_get_audio_sample_label')\n",
    "        return self.annotations.iloc[index, -1]\n",
    "    \n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    ANNOTATIONS_FILE = \"./features_30_sec_final.csv\"\n",
    "    AUDIO_DIR = \"./GTZAN/genres_original\"\n",
    "    SAMPLE_RATE = 22050\n",
    "    NUM_SAMPLES = 22050 * 5 # -> 1 second of audio\n",
    "    plot = True\n",
    "\n",
    "    if torch.cuda.is_available():\n",
    "        device = \"cuda\"\n",
    "    else:\n",
    "        device = \"cpu\"\n",
    "    print(f\"Using {device} device\")\n",
    "\n",
    "    mfcc = torchaudio.transforms.MFCC(\n",
    "        sample_rate=SAMPLE_RATE,\n",
    "        n_mfcc=40,\n",
    "        log_mels=True\n",
    "    )\n",
    "\n",
    "    mel_spectrogram = torchaudio.transforms.MelSpectrogram(\n",
    "        sample_rate=SAMPLE_RATE,\n",
    "        n_fft=1024,\n",
    "        # 窗口大小\n",
    "        hop_length=512,\n",
    "        # 梅尔频度\n",
    "        n_mels=64\n",
    "    )\n",
    "\n",
    "    # objects inside transforms module are callable!\n",
    "    # ms = mel_spectrogram(signal)\n",
    "\n",
    "    gtzan = GTZANDataset(\n",
    "        ANNOTATIONS_FILE,\n",
    "        AUDIO_DIR,\n",
    "        mfcc,\n",
    "        SAMPLE_RATE,\n",
    "        NUM_SAMPLES,\n",
    "        device\n",
    "    )\n",
    "\n",
    "    print(f\"There are {len(gtzan)} samples in the dataset\")\n",
    "\n",
    "    if plot:\n",
    "        signal, label, path = gtzan[666]\n",
    "        print(f'path:{path}')\n",
    "        signal = signal.cpu()\n",
    "        print(signal.shape)\n",
    "        \n",
    "        plt.figure(figsize=(16, 8), facecolor=\"white\")\n",
    "        plt.imshow(signal[0,:,:], origin='lower')\n",
    "        plt.autoscale(False)\n",
    "        plt.xlabel(\"Time\")\n",
    "        plt.ylabel(\"Frequency\")\n",
    "        plt.colorbar()\n",
    "        plt.axis('auto')\n",
    "        plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:13:19.117209Z",
     "iopub.status.busy": "2022-04-25T01:13:19.116942Z",
     "iopub.status.idle": "2022-04-25T01:13:19.125406Z",
     "shell.execute_reply": "2022-04-25T01:13:19.124724Z",
     "shell.execute_reply.started": "2022-04-25T01:13:19.11718Z"
    }
   },
   "outputs": [],
   "source": [
    "ANNOTATIONS_FILE = \"./features_30_sec_final.csv\"\n",
    "AUDIO_DIR = \"./GTZAN/genres_original\"\n",
    "SAMPLE_RATE = 22050\n",
    "NUM_SAMPLES = 22050  * 5\n",
    "\n",
    "# 接下来这三个函数实际在后面没啥作用，可以删除\n",
    "# 创建数据加载集\n",
    "def create_data_loader(train_data, batch_size):\n",
    "    train_dataloader = DataLoader(train_data, batch_size=batch_size, shuffle=True,num_workers=0, pin_memory=True)\n",
    "    return train_dataloader\n",
    "\n",
    "\n",
    "# 对每一个epoch训练\n",
    "def train_single_epoch(model, data_loader, loss_fn, optimiser, device):\n",
    "    for input, target in data_loader:\n",
    "        input, target = input.to(device), target.to(device)\n",
    "\n",
    "        # calculate loss\n",
    "        prediction = model(input)\n",
    "        loss = loss_fn(prediction, target)\n",
    "\n",
    "        # backpropagate error and update weights\n",
    "        optimiser.zero_grad()\n",
    "        loss.backward()\n",
    "        optimiser.step()\n",
    "\n",
    "    print(f\"loss: {loss.item()}\")\n",
    "\n",
    "# 训练\n",
    "def train(model, data_loader, loss_fn, optimiser, device, epochs):\n",
    "    for i in range(epochs):\n",
    "        print(f\"Epoch {i+1}\")\n",
    "        train_single_epoch(model, data_loader, loss_fn, optimiser, device)\n",
    "        print(\"---------------------------\")\n",
    "    print(\"Finished training\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:13:20.289773Z",
     "iopub.status.busy": "2022-04-25T01:13:20.28945Z",
     "iopub.status.idle": "2022-04-25T01:13:20.304247Z",
     "shell.execute_reply": "2022-04-25T01:13:20.303383Z",
     "shell.execute_reply.started": "2022-04-25T01:13:20.289738Z"
    }
   },
   "outputs": [],
   "source": [
    "# AlexNet网络\n",
    "class AlexNet(nn.Module):\n",
    "    def __init__(self, num_classes=10):\n",
    "        super(AlexNet, self).__init__()\n",
    "        self.features = nn.Sequential(\n",
    "            # 卷积 输入通道1，输出通道64 卷积核大小11*11 步长4 零填充2\n",
    "            nn.Conv2d(1, 64, kernel_size=11, stride=4, padding=2),\n",
    "            # ReLU激活函数\n",
    "            nn.ReLU(inplace=True),\n",
    "            # 最大池化\n",
    "            nn.MaxPool2d(kernel_size=3, stride=2),\n",
    "            nn.Conv2d(64, 192, kernel_size=5, padding=2),\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.MaxPool2d(kernel_size=3, stride=2),\n",
    "            nn.Conv2d(192, 384, kernel_size=3, padding=1),\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.Conv2d(384, 256, kernel_size=3, padding=1),\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.Conv2d(256, 256, kernel_size=3, padding=1),\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.MaxPool2d(kernel_size=3, stride=2),\n",
    "        )\n",
    "        # 展开\n",
    "        self.flatten = nn.Flatten()\n",
    "        # 分类器\n",
    "        self.classifier = nn.Sequential(\n",
    "            # 线性分类器 全连接层\n",
    "            nn.Linear(12288, 1024),\n",
    "            nn.ReLU(inplace=True),\n",
    "            # Dropout 随机失活\n",
    "            nn.Dropout(p=0.5, inplace=False),\n",
    "            nn.Linear(1024, 1024),\n",
    "            nn.ReLU(inplace=True),\n",
    "            nn.Dropout(p=0.3, inplace=False),\n",
    "            nn.Linear(1024, num_classes),\n",
    "        )\n",
    "    # 前向传播\n",
    "    def forward(self, x):\n",
    "        x = self.features(x)\n",
    "        #x = x.view(-1, 3072)\n",
    "        x = self.flatten(x)\n",
    "        x = self.classifier(x)\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:13:21.27714Z",
     "iopub.status.busy": "2022-04-25T01:13:21.276884Z",
     "iopub.status.idle": "2022-04-25T01:13:26.252141Z",
     "shell.execute_reply": "2022-04-25T01:13:26.251411Z",
     "shell.execute_reply.started": "2022-04-25T01:13:21.277112Z"
    }
   },
   "outputs": [],
   "source": [
    "if __name__ == '__main__':\n",
    "    from torchsummary import summary\n",
    "    alex=AlexNet().to(\"cuda\")\n",
    "    summary(alex, (1, 128, 111* 5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T01:13:26.254123Z",
     "iopub.status.busy": "2022-04-25T01:13:26.253849Z",
     "iopub.status.idle": "2022-04-25T01:13:26.259628Z",
     "shell.execute_reply": "2022-04-25T01:13:26.258934Z",
     "shell.execute_reply.started": "2022-04-25T01:13:26.254087Z"
    }
   },
   "outputs": [],
   "source": [
    "torch.manual_seed(128)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:12:58.874772Z",
     "iopub.status.busy": "2022-04-25T03:12:58.874493Z",
     "iopub.status.idle": "2022-04-25T03:12:58.879886Z",
     "shell.execute_reply": "2022-04-25T03:12:58.878906Z",
     "shell.execute_reply.started": "2022-04-25T03:12:58.874742Z"
    }
   },
   "outputs": [],
   "source": [
    "# 定义超参数的字典\n",
    "params = OrderedDict(\n",
    "    lr = [.001, .0001]\n",
    "    , batch_size = [64]\n",
    "    , num_workers = [0]\n",
    "    , device = ['cuda']\n",
    "    \n",
    ")\n",
    "\n",
    "# 训练集标签文件地址\n",
    "ANNOTATIONS_FILE = \"./features_30_sec_final.csv\"\n",
    "# 训练集音频文件地址\n",
    "AUDIO_DIR = \"./GTZAN/genres_original\"\n",
    "\n",
    "# 测试集\n",
    "ANNOTATIONS_FILE_TEST = \"./features_30_sec_test_final.csv\"\n",
    "AUDIO_DIR_TEST = \"./GTZAN_TEST/genres_original\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:14:36.206946Z",
     "iopub.status.busy": "2022-04-25T03:14:36.206554Z",
     "iopub.status.idle": "2022-04-25T03:32:44.665671Z",
     "shell.execute_reply": "2022-04-25T03:32:44.664936Z",
     "shell.execute_reply.started": "2022-04-25T03:14:36.206818Z"
    }
   },
   "outputs": [],
   "source": [
    "# 这个每用，用下面的梅尔频谱\n",
    "mfcc = torchaudio.transforms.MFCC(\n",
    "        sample_rate=SAMPLE_RATE,\n",
    "        n_mfcc=128,\n",
    "        log_mels=True\n",
    ")\n",
    "\n",
    "# mel频谱转换\n",
    "mel_spectrogram = torchaudio.transforms.MelSpectrogram(\n",
    "    sample_rate=SAMPLE_RATE,\n",
    "    n_fft=1024,\n",
    "    hop_length=512,\n",
    "    n_mels=64\n",
    ")\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "m = RunManager()\n",
    "# c = 0\n",
    "# acc = 0\n",
    "# now_acc = 0\n",
    "# 下面就是正式训练了\n",
    "for run in RunBuilder.get_runs(params):\n",
    "    usd = GTZANDataset(ANNOTATIONS_FILE,\n",
    "                        AUDIO_DIR,\n",
    "                        mfcc,\n",
    "                        SAMPLE_RATE,\n",
    "                        NUM_SAMPLES,\n",
    "                        run.device)\n",
    "    usd_test = GTZANDataset(\n",
    "        ANNOTATIONS_FILE_TEST,\n",
    "        AUDIO_DIR_TEST,\n",
    "        mfcc,\n",
    "        SAMPLE_RATE,\n",
    "        NUM_SAMPLES,\n",
    "        run.device\n",
    "    )\n",
    "    \n",
    "    print(run)\n",
    "    device = torch.device(run.device)\n",
    "    \n",
    "#     train_dataloader = create_data_loader(usd,\n",
    "#                                          batch_size = run.batch_size,\n",
    "#                                          num_workers = run.num_workers)\n",
    "    \n",
    "    train_data_loader = DataLoader(usd, batch_size=run.batch_size, num_workers = run.num_workers, shuffle=True)\n",
    "    \n",
    "    test_data_loader = DataLoader(usd_test, batch_size=run.batch_size,num_workers = run.num_workers)\n",
    "    \n",
    "    # network=VGG16().to(device)\n",
    "    # network = CNNNetwork().to(device)\n",
    "    #network = ANNNet().to(device)\n",
    "    network = AlexNet().to(device)\n",
    "    print(network)\n",
    "    # 优化器\n",
    "    optimizer = optim.Adam(network.parameters(),lr=run.lr)\n",
    "    m.begin_run(run, network, train_data_loader, test_data_loader)\n",
    "    #best_loss 初始化为正无穷\n",
    "    best_loss = float('inf')\n",
    "    for epoch in range(100):\n",
    "        network.train()\n",
    "        m.begin_epoch()\n",
    "        for batch in train_data_loader:\n",
    "            input = batch[0].to(device)\n",
    "            target = batch[1].to(device)\n",
    "            preds = network(input)\n",
    "            loss = F.cross_entropy(preds,target)\n",
    "            optimizer.zero_grad()\n",
    "            # 反向传播\n",
    "            loss.backward()\n",
    "            optimizer.step()\n",
    "            m.track_loss(loss, batch)\n",
    "            m.track_num_correct(preds, target)\n",
    "                    \n",
    "        with torch.no_grad():\n",
    "            # 这部分用于测试不用于训练所以不计算梯度\n",
    "            for test_batch in test_data_loader:\n",
    "                test_input = batch[0].to(device)\n",
    "                test_target = batch[1].to(device)\n",
    "                test_preds = network(test_input)\n",
    "                test_loss = F.cross_entropy(test_preds,test_target)\n",
    "\n",
    "                m.test_loss(test_loss, test_batch)\n",
    "                \n",
    "                m.test_num_correct(test_preds, test_target)    \n",
    "        m.end_epoch()\n",
    "        \n",
    "    # 保存模型    \n",
    "    torch.save(network.state_dict(), f'best_model_okk.pth')\n",
    "    m.end_run()\n",
    "    m.save(f'{run.lr}_{run.batch_size}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:32:46.886209Z",
     "iopub.status.busy": "2022-04-25T03:32:46.88549Z",
     "iopub.status.idle": "2022-04-25T03:32:48.429682Z",
     "shell.execute_reply": "2022-04-25T03:32:48.428858Z",
     "shell.execute_reply.started": "2022-04-25T03:32:46.88617Z"
    }
   },
   "outputs": [],
   "source": [
    "!zip -r runs.zip runs\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:14:30.720512Z",
     "iopub.status.busy": "2022-04-25T03:14:30.720181Z",
     "iopub.status.idle": "2022-04-25T03:14:32.358837Z",
     "shell.execute_reply": "2022-04-25T03:14:32.357662Z",
     "shell.execute_reply.started": "2022-04-25T03:14:30.720475Z"
    }
   },
   "outputs": [],
   "source": [
    "!rm -rf runs\n",
    "\n",
    "!rm -rf \"runs.zip\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:34:17.682046Z",
     "iopub.status.busy": "2022-04-25T03:34:17.681727Z",
     "iopub.status.idle": "2022-04-25T03:34:17.687101Z",
     "shell.execute_reply": "2022-04-25T03:34:17.686244Z",
     "shell.execute_reply.started": "2022-04-25T03:34:17.682009Z"
    }
   },
   "outputs": [],
   "source": [
    "class_mapping = [\n",
    "    'blues',\n",
    "    'classical',\n",
    "    'country',\n",
    "    'disco',\n",
    "    'hiphop',\n",
    "    'jazz',\n",
    "    'metal',\n",
    "    'pop',\n",
    "    'reggae',\n",
    "    'rock'\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:34:18.696979Z",
     "iopub.status.busy": "2022-04-25T03:34:18.696161Z",
     "iopub.status.idle": "2022-04-25T03:34:18.706431Z",
     "shell.execute_reply": "2022-04-25T03:34:18.705738Z",
     "shell.execute_reply.started": "2022-04-25T03:34:18.696932Z"
    }
   },
   "outputs": [],
   "source": [
    "import random\n",
    "\n",
    "ran = random.sample(range(0,1000),10)\n",
    "ran "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:34:22.679957Z",
     "iopub.status.busy": "2022-04-25T03:34:22.679677Z",
     "iopub.status.idle": "2022-04-25T03:34:22.685403Z",
     "shell.execute_reply": "2022-04-25T03:34:22.684245Z",
     "shell.execute_reply.started": "2022-04-25T03:34:22.679928Z"
    }
   },
   "outputs": [],
   "source": [
    "# X输入mel频谱的张量，y实际的标签下标，class_mapping 标签字典\n",
    "def predict(model, X, y, class_mapping):\n",
    "    model.eval()    # train <-> eval: changes how model behave (e.g. no dropout, ...)\n",
    "    with torch.no_grad():\n",
    "        predictions = model(X)\n",
    "        # tensor (1, 10) -> [ [0.1, 0.04, ..., 0.6] ]\n",
    "        # 取出输出最大的下标\n",
    "        predicted_index = predictions[0].argmax(0)\n",
    "        # 读出预测标签\n",
    "        predicted = class_mapping[predicted_index]\n",
    "        # 实际的标签\n",
    "        expected = class_mapping[y]\n",
    "        \n",
    "    return predicted, expected"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:34:23.661469Z",
     "iopub.status.busy": "2022-04-25T03:34:23.660632Z",
     "iopub.status.idle": "2022-04-25T03:34:46.058923Z",
     "shell.execute_reply": "2022-04-25T03:34:46.05825Z",
     "shell.execute_reply.started": "2022-04-25T03:34:23.6614Z"
    }
   },
   "outputs": [],
   "source": [
    "# 测试下测试集上的精度\n",
    "def verify_acc(local):\n",
    "    \n",
    "    # load back the model\n",
    "    #cnn = CNNNetwork()\n",
    "    # cnn=VGG16()\n",
    "    cnn = AlexNet()\n",
    "    #cnn = ANNNet()\n",
    "    state_dict = torch.load(local)\n",
    "    cnn.load_state_dict(state_dict)\n",
    "\n",
    "    # load gtzan validation dataset\n",
    "    mfcc = torchaudio.transforms.MFCC(\n",
    "        sample_rate=SAMPLE_RATE,\n",
    "        n_mfcc=128,\n",
    "        log_mels=True\n",
    "    )\n",
    "\n",
    "    mel_spectrogram = torchaudio.transforms.MelSpectrogram(\n",
    "        sample_rate=SAMPLE_RATE,\n",
    "        n_fft=1024,\n",
    "        hop_length=512,\n",
    "        n_mels=64\n",
    "    )\n",
    "\n",
    "    gtzan = GTZANDataset(\n",
    "        annotations_file=ANNOTATIONS_FILE,\n",
    "        audio_dir=AUDIO_DIR,\n",
    "        transformation=mfcc,\n",
    "        target_sample_rate=SAMPLE_RATE,\n",
    "        num_samples=NUM_SAMPLES,\n",
    "        device=\"cpu\"\n",
    "    )\n",
    "\n",
    "    count = 0\n",
    "    for i in range(0,800):\n",
    "        index = i\n",
    "\n",
    "        # get a sample from the gtzan dataset for inference\n",
    "        X, y = gtzan[index][0], gtzan[index][1] # [batch_size, num_channels, freq, time]\n",
    "        X.unsqueeze_(0) # insert an extra dimension at index 0\n",
    "        #print(X.shape)\n",
    "        #print(y)\n",
    "\n",
    "        # make an inference\n",
    "        predicted, expected = predict(cnn, X, y, class_mapping)\n",
    "        #print(f\"Predicted: {predicted}\")\n",
    "        #print(f\"Expected: {expected}\")\n",
    "        if predicted == expected:\n",
    "            \n",
    "            count += 1\n",
    "            #print(count)\n",
    "    print(count/800.00)\n",
    "    return (count/800.00) \n",
    "acc = verify_acc(\"best_model_okk.pth\")\n",
    "acc        \n",
    "#         print(f\"Predicted: {predicted}\")\n",
    "#         print(f\"Expected: {expected}\")\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:34:50.739649Z",
     "iopub.status.busy": "2022-04-25T03:34:50.739152Z",
     "iopub.status.idle": "2022-04-25T03:34:51.396895Z",
     "shell.execute_reply": "2022-04-25T03:34:51.396164Z",
     "shell.execute_reply.started": "2022-04-25T03:34:50.739612Z"
    }
   },
   "outputs": [],
   "source": [
    "import random\n",
    "cnn = AlexNet()\n",
    "state_dict = torch.load(\"best_model_okk.pth\")\n",
    "cnn.load_state_dict(state_dict)\n",
    "mfcc = torchaudio.transforms.MFCC(\n",
    "        sample_rate=SAMPLE_RATE,\n",
    "        n_mfcc=128,\n",
    "        log_mels=True\n",
    ")\n",
    "\n",
    "mel_spectrogram = torchaudio.transforms.MelSpectrogram(\n",
    "    sample_rate=SAMPLE_RATE,\n",
    "    n_fft=1024,\n",
    "    hop_length=512,\n",
    "    n_mels=64\n",
    ")\n",
    "\n",
    "gtzan = GTZANDataset(\n",
    "    annotations_file=ANNOTATIONS_FILE,\n",
    "    audio_dir=AUDIO_DIR,\n",
    "    transformation=mfcc,\n",
    "    target_sample_rate=SAMPLE_RATE,\n",
    "    num_samples=NUM_SAMPLES,\n",
    "    device=\"cpu\"\n",
    ")\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "cnn.eval()\n",
    "\n",
    "initial = random.sample(range(0,800),1)[0]\n",
    "print(f'initial:{initial}')\n",
    "\n",
    "music_init_index = gtzan[initial][1]\n",
    "music_init_url = gtzan[initial][2]\n",
    "\n",
    "print(f'music_init:{music_init_url}')\n",
    "\n",
    "\n",
    "ran = random.sample(range(0,800),15)\n",
    "\n",
    "max_music_value = - float(\"inf\")\n",
    "max_music_index = None\n",
    "max_music_url = None\n",
    "real_label_index = None\n",
    "\n",
    "content={}\n",
    "for i in range(15):\n",
    "    with torch.no_grad():\n",
    "        predictions = cnn(gtzan[ran[i]][0].unsqueeze_(0))\n",
    "        predicted_item = predictions[0][music_init_index].item()\n",
    "        if max_music_value < predicted_item:\n",
    "            max_music_value = predicted_item\n",
    "            max_music_index = i\n",
    "            real_label_index = gtzan[ran[i]][1]\n",
    "            max_music_url = gtzan[ran[i]][2]\n",
    "        content[gtzan[ran[i]][2]] = predicted_item\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:34:55.254369Z",
     "iopub.status.busy": "2022-04-25T03:34:55.254078Z",
     "iopub.status.idle": "2022-04-25T03:34:55.25972Z",
     "shell.execute_reply": "2022-04-25T03:34:55.25862Z",
     "shell.execute_reply.started": "2022-04-25T03:34:55.254339Z"
    }
   },
   "outputs": [],
   "source": [
    "class_mapping[music_init_index]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:34:57.294862Z",
     "iopub.status.busy": "2022-04-25T03:34:57.294037Z",
     "iopub.status.idle": "2022-04-25T03:34:57.30296Z",
     "shell.execute_reply": "2022-04-25T03:34:57.302098Z",
     "shell.execute_reply.started": "2022-04-25T03:34:57.294807Z"
    }
   },
   "outputs": [],
   "source": [
    "content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:35:03.159919Z",
     "iopub.status.busy": "2022-04-25T03:35:03.159553Z",
     "iopub.status.idle": "2022-04-25T03:35:03.165826Z",
     "shell.execute_reply": "2022-04-25T03:35:03.165138Z",
     "shell.execute_reply.started": "2022-04-25T03:35:03.159877Z"
    }
   },
   "outputs": [],
   "source": [
    "max_music_value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:35:04.607795Z",
     "iopub.status.busy": "2022-04-25T03:35:04.607495Z",
     "iopub.status.idle": "2022-04-25T03:35:04.615219Z",
     "shell.execute_reply": "2022-04-25T03:35:04.614353Z",
     "shell.execute_reply.started": "2022-04-25T03:35:04.60776Z"
    }
   },
   "outputs": [],
   "source": [
    "max_music_index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:35:05.476156Z",
     "iopub.status.busy": "2022-04-25T03:35:05.475542Z",
     "iopub.status.idle": "2022-04-25T03:35:05.482457Z",
     "shell.execute_reply": "2022-04-25T03:35:05.480746Z",
     "shell.execute_reply.started": "2022-04-25T03:35:05.476119Z"
    }
   },
   "outputs": [],
   "source": [
    "real_label_index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:35:06.474916Z",
     "iopub.status.busy": "2022-04-25T03:35:06.474356Z",
     "iopub.status.idle": "2022-04-25T03:35:06.480476Z",
     "shell.execute_reply": "2022-04-25T03:35:06.479614Z",
     "shell.execute_reply.started": "2022-04-25T03:35:06.474878Z"
    }
   },
   "outputs": [],
   "source": [
    "class_mapping[real_label_index]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-25T03:35:08.136316Z",
     "iopub.status.busy": "2022-04-25T03:35:08.136011Z",
     "iopub.status.idle": "2022-04-25T03:35:08.142047Z",
     "shell.execute_reply": "2022-04-25T03:35:08.141381Z",
     "shell.execute_reply.started": "2022-04-25T03:35:08.136286Z"
    }
   },
   "outputs": [],
   "source": [
    "max_music_url"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2022-04-24T08:41:31.762243Z",
     "iopub.status.busy": "2022-04-24T08:41:31.761981Z",
     "iopub.status.idle": "2022-04-24T08:41:31.769045Z",
     "shell.execute_reply": "2022-04-24T08:41:31.768202Z",
     "shell.execute_reply.started": "2022-04-24T08:41:31.762212Z"
    }
   },
   "outputs": [],
   "source": [
    "ran = random.sample(range(0,1000),10)\n",
    "for i in range(10):\n",
    "    print(ran[i])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
